/*
 * AbstractDrawPage.cpp
 *
 *  Created on: 2010-9-26
 *      Author: wenjian
 */

#include "AbstractDrawPage.h"

using namespace Thk;
namespace Ed {

  AbstractDrawPage::AbstractDrawPage() : mouseEventMode(MEventMode_Hovering),
    mouseHoveringLayer(NULL), manualModeLayer(NULL), focusLayer(NULL) {


  }

  AbstractDrawPage::~AbstractDrawPage() {


  }


  bool AbstractDrawPage::handle(const Event* e){
    //处理图层Modified状态被修改事件
    if(e->getType() == ModifiedEvent::Type){
      const ModifiedEvent* me = (const ModifiedEvent*)e;
      if(me->getModifiedSupport()->isModified()){
        //当层被修改时，设置画布被修改标记
        setModified(true);
        return true;
      }
    }
    return false;
  }

  bool AbstractDrawPage::addLayer(AbstractLayer* l, int pos){
    if(!l){
      return false;
    }
    int layersSize = layers.size();
    pos = pos<0?0:((pos>layersSize)?layersSize:pos);
    Layers::iterator it = find(layers.begin(), layers.end(), l);
    Layers::iterator begin = layers.begin();
    if (it != layers.end()){
      if(pos<layersSize && *it == layers[pos]){
        return true;
      }
      if((it-begin)<pos){
        pos--;
      }
      layers.erase(it);
    }else{
      l->setDrawPage(this);
      //向图层加入ModifiedEvent事件监听器, 监听层的Modified状态
      l->addListener(ModifiedEvent::Type, this);
    }
    layers.insert(begin+pos, l);
    //设置层被修改标记
    setModified(true);
    return true;
  }

  bool AbstractDrawPage::removeLayer(AbstractLayer* l) {
    if(!l){
      return false;
    }
    Layers::iterator it = find(layers.begin(), layers.end(), l);
    if (it != layers.end()) {
      layers.erase(it);
      //移除监听器
      l->removeListener(this);

      //设置层被修改标记
      setModified(true);
      return true;
    }
    return false;
  }

  bool AbstractDrawPage::trackEvent(const Event* e){
    if(MouseEvent::isMouseEvent(e)){
      MouseEvent* me = (MouseEvent*)e;
      //如果是鼠标事件
      int x = (int)(me->x()-this->x());
      int y = (int)(me->y()-this->y());
      if(me->getType() == WheelEvent::Type){
        WheelEvent nme((WheelEvent&)(*me));
        nme.setX(x);
        nme.setY(y);
        nme.setPageEvent(&nme);
        nme.setSource(this);
        return handleMouseEvent(&nme);
      }else{
        MouseEvent nme(*me);
        nme.setX(x);
        nme.setY(y);
        nme.setPageEvent(&nme);
        nme.setSource(this);
        return handleMouseEvent(&nme);
      }
    }else{
      //e->setSource(this);
      if(event(e)){
        return true;
      }
      if(focusLayer && focusLayer->isEventEnabled()){
        return focusLayer->trackEvent(e);
      }
      return false;
    }
  }

//  /**
//   * 处理鼠标事件
//   */
//  bool AbstractDrawPage::handleMouseEvent(const MouseEvent* me){
//    real x = me->x();
//    real y = me->y();
//
//    //在画布中分发鼠标事件
//    event(me);
//
//    //向层转发鼠标事件
//    AbstractLayer* layer = getHoveringLayer(x, y);
//    if(mouseHoveringLayer && mouseHoveringLayer != layer){
//      mouseHoveringLayer->mouseLeave(); //离开层
//      //mouseLeaveLayer(mouseHoveringLayer);
//    }
//    if(mouseHoveringLayer != layer){
//      mouseHoveringLayer = layer;
//      mouseHoveringLayer->mouseEnter();
//    }
//    return layerTrackEvent(layer, me);
//  }


  /**
   * 处理鼠标事件
   */
  bool AbstractDrawPage::handleMouseEvent(const MouseEvent* me){
    real x = me->x();
    real y = me->y();

    //在画布中分发鼠标事件
    event(me);

    //向层转发鼠标事件
    AbstractLayer* layer;
    switch(mouseEventMode){
      case MEventMode_Hovering:
        layer = getHoveringLayer(x, y);
        if(mouseHoveringLayer && mouseHoveringLayer != layer){
          mouseHoveringLayer->mouseLeave(); //离开层
          //mouseLeaveLayer(mouseHoveringLayer);
        }
        if(mouseHoveringLayer != layer){
          mouseHoveringLayer = layer;
          mouseHoveringLayer->mouseEnter();
        }
        return layerTrackEvent(layer, me);
        //layer->trackEvent(me);
       break;
      case MEventMode_Top:
        if(!layers.empty()){
          layer = layers[layers.size()-1];
          if(layer->isEventEnabled() && layer->isVisible() && layer->intersects(x, y)){
            if(mouseHoveringLayer != layer){
              mouseHoveringLayer = layer;
              mouseHoveringLayer->mouseEnter();
            }
            //return layer->trackEvent(me);
            return layerTrackEvent(layer, me);
          }else{
            layer->mouseLeave(); //离开层
            //mouseLeaveLayer(layer);
          }
        }
       break;
      case MEventMode_Manual:
        if(manualModeLayer
            && manualModeLayer->isEventEnabled()
            && manualModeLayer->isVisible()
            && manualModeLayer->intersects(x, y)){
          if(mouseHoveringLayer != manualModeLayer){
            mouseHoveringLayer = manualModeLayer;
            mouseHoveringLayer->mouseEnter();
          }
          return layerTrackEvent(mouseHoveringLayer, me);
          //mouseHoveringLayer->trackEvent(me);
        }else{
          if(mouseHoveringLayer){
            mouseHoveringLayer->mouseLeave(); //离开层
            //mouseLeaveLayer(mouseHoveringLayer);
          }
        }
    }

    return false;
  }

  bool AbstractDrawPage::layerTrackEvent(AbstractLayer* layer, const MouseEvent* me){
    if(!layer)return false;
    if(me->getType() == WheelEvent::Type){
      WheelEvent nme((const WheelEvent&)*me);
      nme.setX((int)(me->x()-layer->x()));
      nme.setY((int)(me->y()-layer->y()));
      nme.setLayerEvent(&nme);
      nme.setSource(layer);
      return layer->trackEvent(&nme);
    }else{
      MouseEvent nme(*me);
      nme.setX((int)(me->x()-layer->x()));
      nme.setY((int)(me->y()-layer->y()));
      nme.setLayerEvent(&nme);
      nme.setSource(layer);
      return layer->trackEvent(&nme);
    }
  }

  AbstractLayer* AbstractDrawPage::getHoveringLayer(real x, real y){
    Layers::reverse_iterator it = layers.rbegin();
    for(; it != layers.rend(); it++){
      AbstractLayer* l = *it;
      if (l->isEventEnabled() && l->isVisible() && l->intersects(x, y)){
        return *it;
      }
    }
    return NULL;
  }

//  /**
//   * 鼠标离开层
//   */
//  void AbstractDrawPage::mouseLeaveLayer(AbstractLayer* layer){
//    layer->mouseLeave(); //离开层
//  }
}
